import { useDebounceFn, useThrottle } from '@vueuse/core';
import type { FunctionArgs } from '@vueuse/core';
import type { Ref } from 'vue';

export type RemoveEventFn = () => void;

export interface UseEventListenerParams {
  el?: Element | Ref<Element | null | undefined> | Window | any;
  eventName: string;
  listener: EventListener | ((this: Element, ev: Event) => any) | Ref<unknown> | FunctionArgs<any[], void>;
  options?: boolean | AddEventListenerOptions;
  autoRemove?: boolean;
  isDebounce?: boolean;
  wait?: number;
}

const useEventListener = ({ el = window, eventName, listener, options, autoRemove = true, isDebounce = true, wait = 80 }: UseEventListenerParams) => {
  let remove: RemoveEventFn = () => {};
  const isAddRef = ref(false);
  if (el) {
    const element: Ref<Element> = ref(el as Element);

    const handler = isDebounce ? useDebounceFn(listener as FunctionArgs<any[], void>, wait) : useThrottle(listener as Ref<unknown>, wait);

    const realHandler = wait ? handler : listener;
    const removeEventListener = (el: Element) => {
      isAddRef.value = true;
      el.removeEventListener(eventName, realHandler as (this: Element, ev: Event) => any, options);
    };

    const addEventListener = (el: Element) => el.addEventListener(eventName, realHandler as (this: Element, ev: Event) => any, options);

    const removeWatch = watch(
      element,
      (v, ov, onCleanup) => {
        console.log('removeWatch~');
        if (v) {
          !unref(isAddRef) && addEventListener(v);
          // onCleanup 一个用于注册副作用清理的回调函数。该回调函数会在副作用下一次重新执行前调用，可以用来清除无效的副作用，例如等待中的异步请求。
          onCleanup(() => autoRemove && removeEventListener(v));
        }
      },
      { immediate: true }
    );

    remove = () => {
      removeEventListener(element.value);
      removeWatch();
    };
  }
  return { removeEvent: remove };
};

export default useEventListener;
